package com.andy.blog.admin.service.impl;

import com.andy.blog.admin.dto.SysRoleDTO;
import com.andy.blog.admin.dto.SysUserDTO;
import com.andy.blog.admin.service.SysPermissionBusService;
import com.andy.blog.admin.service.SysRoleBusService;
import com.andy.blog.admin.service.SysRoleMenuBusService;
import com.andy.blog.common.core.domain.entity.SysRole;
import com.andy.blog.common.core.domain.model.LoginUser;
import com.andy.blog.common.enums.DeleteTypeEnum;
import com.andy.blog.common.exception.BlogServiceException;
import com.andy.blog.common.page.PageUtilsDTO;
import com.andy.blog.common.reponse.BlogResultCode;
import com.andy.blog.common.utils.SecurityUtils;
import com.andy.blog.common.utils.TransformUtils;
import com.andy.blog.dal.domain.SysRoleDO;
import com.andy.blog.dal.domain.SysUserDO;
import com.andy.blog.dal.domain.SysUserRoleDO;
import com.andy.blog.dal.service.SysRoleDalService;
import com.andy.blog.dal.service.SysRoleMenuDalService;
import com.andy.blog.dal.service.SysUserDalService;
import com.andy.blog.dal.service.SysUserRoleDalService;
import com.andy.blog.dal.vo.SysRoleMenuVO;
import com.andy.blog.dal.vo.SysRoleVO;
import com.andy.blog.dal.vo.SysUserRoleVO;
import com.andy.blog.framework.web.service.TokenService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.andy.blog.common.utils.SecurityUtils.getLoginUser;

/**
 * Created by andy on 2023-04-15 9:42
 */
@Service("sysRoleBusService")
public class SysRoleBusServiceImpl implements SysRoleBusService {

    @Resource
    private SysRoleDalService sysRoleDalService;

    @Autowired
    private SysPermissionBusService sysPermissionBusService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysUserDalService sysUserDalService;

    @Resource
    private SysRoleMenuDalService sysRoleMenuDalService;

    @Resource
    private SysUserRoleDalService sysUserRoleDalService;

    @Resource
    private SysRoleMenuBusService sysRoleMenuBusService;


    @Override
    public PageUtilsDTO<SysRoleDTO> listPage(SysRoleVO sysRoleVO) {
        IPage<SysRoleDO> sysRoleDOIPage = sysRoleDalService.selectRoleListPage(sysRoleVO);
        return PageUtilsDTO.build(sysRoleDOIPage.getTotal(), TransformUtils.transformList(sysRoleDOIPage.getRecords(), SysRoleDTO.class));
    }

    @Override
    public SysRole selectRoleById(Long roleId) {
        SysRoleDO sysRoleDO = sysRoleDalService.selectRoleById(roleId);
        return TransformUtils.transform(sysRoleDO, SysRole.class);
    }



    @Override
    public void insertRole(SysRoleVO sysRoleVO) {
        if (!sysRoleDalService.checkRoleNameUnique(sysRoleVO)) {
            throw new BlogServiceException("新增角色'" + sysRoleVO.getRoleName() + "'失败，角色名称已存在");
        } else if (!sysRoleDalService.checkRoleKeyUnique(sysRoleVO)) {
            throw new BlogServiceException("新增角色'" + sysRoleVO.getRoleName() + "'失败，角色权限已存在");
        }

        sysRoleDalService.insertRole(sysRoleVO);

        // 新增用户与菜单关联
        List<SysRoleMenuVO> list = sysRoleVO.getMenuIds().stream()
                .map(menuId -> SysRoleMenuVO.builder().roleId(sysRoleVO.getId()).menuId(menuId).build())
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(list)) {
            sysRoleMenuBusService.insertRoleMenu(list);
        }
    }

    @Override
    public boolean checkRoleNameUnique(SysRole role) {
        //return sysRoleDalService.checkRoleNameUnique(role);
        return true;
    }

    @Override
    public boolean checkRoleKeyUnique(SysRole role) {
        return true;
        //return sysRoleDalService.checkRoleKeyUnique(role);
    }

    @Override
    public void changeStatus(SysRoleVO sysRoleVO) {
        if (Objects.isNull(sysRoleVO.getId())) {
            throw new BlogServiceException(BlogResultCode.BLOG_000001, "角色ID不能为空");
        }

        if (SecurityUtils.isAdminByRoleId(sysRoleVO.getId())) {
            throw new BlogServiceException("不允许操作超级管理员角色");
        }

        sysRoleDalService.updateById(sysRoleVO);
    }

    @Override
    public SysRoleDTO getInfo(Long roleId) {
        SysRoleDO sysRoleDO = sysRoleDalService.selectRoleById(roleId);
        return TransformUtils.transform(sysRoleDO, SysRoleDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysRoleVO sysRoleVO) {
        if (SecurityUtils.isAdminByRoleId(sysRoleVO.getId())) {
            throw new BlogServiceException("不允许操作超级管理员角色");
        }

        if (!sysRoleDalService.checkRoleNameUnique(sysRoleVO)) {
            throw new BlogServiceException("修改角色'" + sysRoleVO.getRoleName() + "'失败，角色名称已存在");
        } else if (!sysRoleDalService.checkRoleKeyUnique(sysRoleVO)) {
            throw new BlogServiceException("修改角色'" + sysRoleVO.getRoleName() + "'失败，角色权限已存在");
        }

        sysRoleDalService.updateById(sysRoleVO);

        // 删除角色与菜单关联
        sysRoleMenuDalService.deleteRoleMenuByRoleId(sysRoleVO.getId());
        // 新增用户与菜单关联
        List<SysRoleMenuVO> list = sysRoleVO.getMenuIds().stream().map(menuId -> SysRoleMenuVO.builder().roleId(sysRoleVO.getId()).menuId(menuId).build())
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(list)) {
            sysRoleMenuBusService.insertRoleMenu(list);
        }

        // 更新缓存用户权限
        LoginUser loginUser = getLoginUser();
        if (Objects.nonNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) {
            loginUser.setPermissions(sysPermissionBusService.getMenuPermission(loginUser.getUser()));
            loginUser.setUser(sysUserDalService.selectUserByUserName(loginUser.getUser().getUserName()));
            tokenService.setLoginUser(loginUser);
        }
    }

    @Override
    public List<SysUserDTO> selectAllocatedList(SysRoleVO sysRoleVO) {
        if (Objects.isNull(sysRoleVO.getId())) {
            throw new BlogServiceException("角色id不能为空");
        }

        List<SysUserRoleDO> sysUserRoleDOS = sysUserRoleDalService.selectByRoleId(sysRoleVO.getId());

        List<SysUserDTO> dataList = new ArrayList<>();
        for (SysUserRoleDO sysUserRoleDO : sysUserRoleDOS) {

            SysUserDO sysUserDO = sysUserDalService.selectById(sysUserRoleDO.getUserId());
            if (DeleteTypeEnum.DELETE_N.getCode().equals(sysUserDO.getIsDeleted())) {
                dataList.add(TransformUtils.transform(sysUserDO, SysUserDTO.class));
            }
        }
        return dataList;
    }

    @Override
    public void deleteAuthUser(SysUserRoleVO sysUserRoleVO) {
        sysUserRoleDalService.deleteAuthUser(sysUserRoleVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoleById(Long roleId) {
        boolean isAdminRole = SecurityUtils.isAdminByRoleId(roleId);
        if (isAdminRole) {
            throw new BlogServiceException("不允许操作超级管理员角色");
        }

        SysRoleDO role = sysRoleDalService.selectRoleById(roleId);
        if (sysRoleDalService.countUserRoleByRoleId(roleId) > 0) {
            throw new BlogServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
        }

        // 删除角色与菜单关联
        sysRoleDalService.deleteRoleById(roleId);
    }
}
